﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MoveCalculator.cs" company="">
//   
// </copyright>
//  <summary>
//   The move calculator.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Shatranj
{
    using System.Collections.Generic;
    using System.Reflection;

    /// <summary>
    /// The move calculator.
    /// </summary>
    public abstract class MoveCalculator
    {
        // private static IDictionary<Piece, IDictionary<string, ICollection<MovePath>>> Paths { get; set; }
        // public static void CachePaths()
        // {
        // var document =
        // XDocument.Load(XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("Shatranj.LegalMoves.xml")));
        // var elements = document.Descendants("piece");
        // Paths = new Dictionary<Piece, IDictionary<string, ICollection<MovePath>>>();
        // foreach (var element in elements)
        // {

        // var paths = element.Descendants("movepath");
        // var spec = element.Descendants("speciality").First();

        // var groupDictionary = new Dictionary<string, ICollection<MovePath>>();
        // foreach (var path in paths)
        // {
        // var movePath = new MovePath()
        // {
        // Direction =
        // (MoveDirection)
        // Enum.Parse(typeof (MoveDirection), path.Attribute("direction").Value),
        // Ordinal = 1,
        // MinStep = int.Parse(path.Attribute("minstep").Value),
        // MaxStep = int.Parse(path.Attribute("maxstep").Value),
        // Speciality = new PieceSpeciality
        // {
        // CanCaptureAcross =
        // bool.Parse(spec.Attribute("captureAcross").Value),
        // CanJumpOver = bool.Parse(spec.Attribute("canJumpOver").Value),
        // IsPromotable = bool.Parse(spec.Attribute("isPromotable").Value),
        // Enpassant = bool.Parse(spec.Attribute("enpassant").Value),
        // InitialMaxStepAllowed = bool.Parse(spec.Attribute("initialMaxStepAllowed").Value),
        // InitialMaxStep = int.Parse(spec.Attribute("initialMaxStep").Value)

        // }

        // };

        // movePath.GroupId = path.Attribute("groupid").Value;
        // if(!groupDictionary.ContainsKey(movePath.GroupId))
        // {
        // groupDictionary[movePath.GroupId] = new List<MovePath>();
        // }

        // groupDictionary[movePath.GroupId].Add(movePath);

        // }

        // var piece = (Piece) Enum.Parse(typeof (Piece), element.Attribute("id").Value);
        // Paths.Add(piece, groupDictionary);
        // }
        // }
        #region Public Methods and Operators

        /// <summary>
        /// The calculate.
        /// </summary>
        /// <param name="piece">
        /// The piece.
        /// </param>
        /// <param name="currentLocation">
        /// The current location.
        /// </param>
        /// <param name="options">
        /// The options.
        /// </param>
        /// <returns>
        /// The <see cref="ICollection"/>.
        /// </returns>
        public static ICollection<BoardSquare> Calculate(
            ChessPiece piece, 
            BoardSquare currentLocation, 
            MoveOptions options)
        {
            currentLocation.IsHit = true;
            foreach (var group in piece.MovePaths)
            {
                var groupid = group.Key;
                var paths = group.Value;

                foreach (var path in paths)
                {
                    int i;
                    if (piece.TimesMoved == 0 && piece.InitialMaxStepAllowed)
                    {
                        i = piece.InitialMaxStep;
                    }
                    else
                    {
                        i = path.MaxStep;
                    }

                    var loc = currentLocation;

                    // Knight is the only piece that carries a groupid.. 
                    // Other pieces move till they encounter a piece of the same force or till a piece of the opposing force that can be captured
                    // So, we do not have to worry about hit calculation.
                    // Unfortunately, this also means, we need to check beforehand if any of end location carries a piece of the same force
                    var lastloc = currentLocation;
                    if (piece.CanJumpOver)
                    {
                        for (int y = 0; y < i; y++)
                        {
                            loc =
                                loc.GetType()
                                    .InvokeMember(path.Direction.ToString(), BindingFlags.GetProperty, null, loc, null)
                                as BoardSquare;
                            if (loc == null)
                            {
                                break;
                            }

                            lastloc = loc;
                        }

                        if (!lastloc.IsEmpty && lastloc.CurrentPiece.Force != currentLocation.CurrentPiece.Force)
                        {
                            // Move path one tanget valid
                        }
                    }

                    loc = currentLocation;
                    for (int y = path.MinStep; y <= i; y++)
                    {
                        loc =
                            loc.GetType()
                                .InvokeMember(path.Direction.ToString(), BindingFlags.GetProperty, null, loc, null) as
                            BoardSquare;
                        if (loc == null)
                        {
                            break;
                        }

                        if (!piece.CanJumpOver && !loc.IsEmpty
                            && loc.CurrentPiece.Force == currentLocation.CurrentPiece.Force)
                        {
                            break;
                        }

                        loc.IsHit = true;
                        if (!piece.CanJumpOver && !loc.IsEmpty
                            && loc.CurrentPiece.Force != currentLocation.CurrentPiece.Force)
                        {
                            break;
                        }
                    }
                }
            }

            return null;
        }

        #endregion
    }
}